package com.docker.core.third.docker;

import com.docker.comment.ShellUtil;
import com.docker.core.mvc.Remark;
import com.docker.core.third.websocket.WebsocketKit;
import com.docker.manege.container.ContainerBean;
import com.github.dockerjava.api.DockerClient;
import com.github.dockerjava.api.async.ResultCallback;
import com.github.dockerjava.api.async.ResultCallbackTemplate;
import com.github.dockerjava.api.command.*;
import com.github.dockerjava.api.model.*;
import com.jfinal.kit.StrKit;
import com.jfinal.plugin.activerecord.Record;
import kit.docker.datetime.DateKit;
import kit.docker.exception.BaseException;

import java.io.*;
import java.nio.charset.StandardCharsets;
import java.util.*;

/**
 * @Author ldl
 * @Create 2020/12/01 001 11:48
 */
@Remark("docker工具类")
public class DockerKit extends BaseDocker {

    /**
     * @Param: [token 用户登录状态, serverId 服务器id]
     * @return: TODO
     * @Author: ldl
     * @Create: 2020/12/02 002 16:01
     */
    @Remark("获取连接标识")
    public static String key(String token, String serverId) {
        return token + ":" + serverId;
    }

    /**
     * @Param: []
     * @return: TODO
     * @Author: ldl
     * @Create: 2020/12/03 003 14:38
     */
    @Remark("整理连接池")
    public static boolean tidy() {
        Map<String, SelfDockerClient> clientPool = getClientPool();
        for (String clientKey : clientPool.keySet()) {
            Long lastConnectTime = clientPool.get(clientKey).getLast_connect_time();
            long min = (DateKit.getNowTimestamp() - lastConnectTime) / 60;
            if (min > 30) {//超过30分钟没有操作，则关闭该连接
                close(clientKey);
            }
        }
        return true;
    }

    /**
     * @Param: [clientKey]
     * @return: TODO
     * @Author: ldl
     * @Create: 2020/12/03 003 14:39
     */
    @Remark("更新最后通讯时间")
    public static boolean refreshLCTime(String clientKey) {
        refreshTime(clientKey);
        return true;
    }

    /**
     * @Param: [dockerClient]
     * @return: TODO
     * @Author: ldl
     * @Create: 2020/12/03 003 14:49
     */
    @Remark("更新最后通讯时间")
    public static boolean refreshLCTime(SelfDockerClient dockerClient) {
        refreshTime(dockerClient);
        return true;
    }

    public static SelfDockerClient getSeflClient(String clientKey) {
        return getSeflDockerClient(clientKey);
    }

    /**
     * @Param: [clientKey]
     * @return: TODO
     * @Author: ldl
     * @Create: 2020/12/03 003 14:49
     */
    @Remark("获取最后通讯时间")
    public static Long getLCTime(String clientKey) {
        return getTime(clientKey);
    }

    /**
     * @Param: [dockerConfig]
     * @return: TODO
     * @Author: ldl
     * @Create: 2020/12/01 001 15:16
     */
    @Remark("docker连接")
    public static boolean connect(String clientKey, Record docker) {
        return connectDocker(clientKey, docker);
    }

    /**
     * @Param: []
     * @return: TODO
     * @Author: ldl
     * @Create: 2020/12/01 001 15:17
     */
    @Remark("关闭docker连接")
    public static boolean colse(String clientKey) {
        return close(clientKey);
    }

    /**
     * @Param: []
     * @return: TODO
     * @Author: ldl
     * @Create: 2020/12/01 001 15:21
     */
    @Remark("获取镜像列表")
    public static List<Image> images(String clientKey, String imageName) {
        ListImagesCmd listImagesCmd = getDockerClient(clientKey).listImagesCmd();
        listImagesCmd.withShowAll(true);//是否查询出所有镜像，默认为true
        if (StrKit.notBlank(imageName)) {
            //根据镜像名称查询，镜像名称需要为全名称，无法模糊查询
            listImagesCmd.withImageNameFilter(imageName);
        }
        try {
            return listImagesCmd.exec();
        } catch (Exception e) {
            throw new BaseException(e.getMessage());
        }
    }

    /**
     * @Param: [dockerClient, term]
     * @return: TODO
     * @Author: ldl
     * @Create: 2021/01/11 011 09:59
     */
    @Remark("搜索镜像")
    public static List<SearchItem> searchImage(DockerClient dockerClient, String term) {
        try {
            return dockerClient.searchImagesCmd(term).exec();
        } catch (Exception e) {
            throw new BaseException(e.getMessage());
        }
    }

    /**
     * @Param: [clientKey, term]
     * @return: TODO
     * @Author: ldl
     * @Create: 2021/01/11 011 09:59
     */
    @Remark("搜索镜像")
    public static List<SearchItem> searchImage(String clientKey, String term) {
        return searchImage(getDockerClient(clientKey), term);
    }

    /**
     * @Param: [dockerClient, term]
     * @return: TODO
     * @Author: ldl
     * @Create: 2021/01/11 011 10:00
     */
    @Remark("搜索镜像")
    public static List<SearchItem> searchImage(SelfDockerClient dockerClient, String term) {
        return searchImage(dockerClient.getDockerClient(), term);
    }

    /**
     * @Param: [dockerClient, term]
     * @return: TODO
     * @Author: ldl
     * @Create: 2021/01/11 011 10:01
     */
    @Remark("拉取镜像")
    public static boolean pullImage(SelfDockerClient dockerClient, String term, String connectKey) {
        return pullImage(dockerClient.getDockerClient(), term, connectKey);
    }

    /**
     * @Param: [dockerClient, term]
     * @return: TODO
     * @Author: ldl
     * @Create: 2021/01/11 011 10:01
     */
    @Remark("拉取镜像")
    public static boolean pullImage(DockerClient dockerClient, String repository, String connectKey) {
        try {
            if (StrKit.isBlank(connectKey)) {
                ResultCallback.Adapter<PullResponseItem> start = dockerClient.pullImageCmd(repository).start();
            } else {
                dockerClient.pullImageCmd(repository).exec(new ResultCallback<PullResponseItem>() {
                    public void onStart(Closeable closeable) {
                        WebsocketKit.sendMsg(connectKey, "image_pull_response", "pull start.");
                    }

                    public void onNext(PullResponseItem object) {
                        WebsocketKit.sendMsg(connectKey, "image_pull_response", object.getStatus() + "\t"
                                + (StrKit.notNull(object.getProgressDetail()) ? object.getProgressDetail() : ""));
                    }

                    public void onError(Throwable throwable) {
                        WebsocketKit.sendMsg(connectKey, "image_pull_response", "pull error:  " + throwable.getMessage());
                    }

                    public void onComplete() {
                        WebsocketKit.sendMsg(connectKey, "image_pull_response", "pull finished.");
                    }

                    public void close() throws IOException {
                        WebsocketKit.sendMsg(connectKey, "image_pull_response", "pull close.");
                    }
                });
            }
        } catch (Exception e) {
            throw new BaseException(e.getMessage());
        }
        return true;
    }

    /**
     * @Param: [clientKey, term]
     * @return: TODO
     * @Author: ldl
     * @Create: 2021/01/11 011 10:06
     */
    @Remark("拉取镜像")
    public static boolean pullImage(String clientKey, String term, String connectKey) {
        return pullImage(getDockerClient(clientKey), term, connectKey);
    }

    /**
     * @Param: [dockerClient, imageId]
     * @return: TODO
     * @Author: ldl
     * @Create: 2021/01/11 011 10:06
     */
    @Remark("删除镜像")
    public static boolean removeImage(DockerClient dockerClient, String imageId, String force) {
        try {
            RemoveImageCmd removeImageCmd = dockerClient.removeImageCmd(imageId);
            if ("1".equals(force)) {
                //force=true,强制删除
                removeImageCmd.withForce(true);
            } else {
                removeImageCmd.withForce(false);
            }
            removeImageCmd.exec();
        } catch (Exception e) {
            throw new BaseException(e.getMessage());
        }
        return true;
    }

    /**
     * @Param: [dockerClient, imageId]
     * @return: TODO
     * @Author: ldl
     * @Create: 2021/01/11 011 10:07
     */
    @Remark("删除镜像")
    public static boolean removeImage(SelfDockerClient dockerClient, String imageId, String force) {
        return removeImage(dockerClient.getDockerClient(), imageId, force);
    }

    /**
     * @Param: [clientKey, imageId]
     * @return: TODO
     * @Author: ldl
     * @Create: 2021/01/11 011 10:07
     */
    @Remark("删除镜像")
    public static boolean removeImage(String clientKey, String imageId, String force) {
        return removeImage(getDockerClient(clientKey), imageId, force);
    }

    public static void main(String[] args) throws InterruptedException {
        String clientKey = "abc134";
        Record docker = new Record();
        docker.set("docker_host", "192.168.1.142");
        docker.set("docker_port", "2376");
        docker.set("cert_path", "D:\\docker\\142");
        docker.set("config_path", "D:\\docker\\142");
        docker.set("api_version", "1.40");
        docker.set("max_connect", 5);
        DockerClient dockerClient = connectDocker2(clientKey, docker);

        ExecCreateCmdResponse execInstance2 = createExecInstance(dockerClient, "8acf30bb1ac5d2fd559dabd3b854e07dc7de9f92efee0975765d57044979ec60", "/bin/bash");

        PipedOutputStream outputStream = new PipedOutputStream();
//        execInstance(dockerClient, execInstance2.getId(), outputStream);

        new Thread(() -> {
            Scanner scanner = new Scanner(System.in);
            try {
                while (scanner.hasNext()) {
                    outputStream.write((scanner.nextLine() + "\r").getBytes());
                }
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                try {
                    // 关闭输出流
                    outputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }).start();

        try {
            Thread.sleep(1000000L);
        } catch (Exception e) {
            e.printStackTrace();
        }

//        ContainerCreateBean containerCreateBean = new ContainerCreateBean();
//        containerCreateBean.setImage_name("redis:latest");
//        containerCreateBean.setContainer_name("test_redis");
//        containerCreateBean.setBind_port("16384:6379|16385:80");
//        containerCreateBean.setMount_path("/home/java/test_docker/redis:/data");
//        containerCreateBean.setAlways_restart("1");
//        containerCreateBean.setEnv("POSTGRESQL_ADMIN_PASSWORD=pajx000000");
//        containerCreateBean.setCmd("--appendonly yes|--requirepass hnzm@87539800");
//        CreateContainerResponse container = createContainer(dockerClient, containerCreateBean);
//        System.out.println(container);
//        startContainer(dockerClient, container.getId());
//        removeContainer(dockerClient, "TomcatTest");

    }

    /**
     * @Param: [containerCreateBean]
     * @return: TODO
     * @Author: ldl
     * @Create: 2021/01/08 008 15:22
     */
    @Remark("创建容器")
    public static CreateContainerResponse createContainer(DockerClient dockerClient, ContainerBean containerBean) {
        //映射端口，暴露端口:内部端口
        List<PortBinding> portBindings = new ArrayList<>();
        String bindPort = containerBean.getBind_port();
        if (StrKit.notBlank(bindPort)) {
            String[] bindPorts = bindPort.split("\\|");
            for (String port : bindPorts) {
                String[] ports = port.split(":");
                if (ports.length != 2) {
                    throw new BaseException("端口映射不合法");
                }
                portBindings.add(new PortBinding(Ports.Binding.bindPort(Integer.parseInt(ports[0]))
                        , ExposedPort.tcp(Integer.parseInt(ports[1]))));
            }
        }

        //挂载目录，宿主机路径:容器路径
        List<Mount> mounts = new ArrayList<>();
        String mountPath = containerBean.getMount_path();
        if (StrKit.notBlank(mountPath)) {
            String[] mountPaths = mountPath.split("\\|");
            for (String path : mountPaths) {
                String[] paths = path.split(":");
                if (paths.length != 2) {
                    throw new BaseException("挂载路径不合法");
                }
                //source-宿主机路径，target-容器路径
                mounts.add(new Mount().withSource(paths[0]).withTarget(paths[1]).withType(MountType.BIND));
            }
        }

        HostConfig hostConfig = new HostConfig();

        //端口绑定
        if (portBindings.size() > 0) {
            hostConfig.withPortBindings(portBindings);
        }

        //挂载目录
        if (mounts.size() > 0) {
            hostConfig.withMounts(mounts);
        }

        //跟随服务自动重启
        if ("1".equals(containerBean.getAlways_restart())) {
            hostConfig.withRestartPolicy(RestartPolicy.alwaysRestart());
        }

        //工作网络
        if (StrKit.notBlank(containerBean.getNet_work())) {
            hostConfig.withNetworkMode(containerBean.getNet_work());
        }

        CreateContainerCmd containerCmd = dockerClient.createContainerCmd(containerBean.getImage_name())
                .withHostConfig(hostConfig);

        //容器名称
        if (StrKit.notBlank(containerBean.getContainer_name())) {
            containerCmd.withName(containerBean.getContainer_name());
        }

        //cmd命令
        if (StrKit.notBlank(containerBean.getCmd())) {
            containerCmd.withCmd(containerBean.getCmd().split("\\|"));
        }

        //环境变量
        if (StrKit.notBlank(containerBean.getEnv())) {
            containerCmd.withEnv(containerBean.getEnv().split("\\|"));
        }

        //ip4地址设置
        if (StrKit.notBlank(containerBean.getNet_work(), containerBean.getIp4_address())) {
            containerCmd.withIpv4Address(containerBean.getIp4_address());
        }

        //ip6地址设置
        if (StrKit.notBlank(containerBean.getNet_work(), containerBean.getIp6_address())) {
            containerCmd.withIpv6Address(containerBean.getIp6_address());
        }

        //工作路径
        if (StrKit.notBlank(containerBean.getWorking_dir())) {
            containerCmd.withWorkingDir(containerBean.getWorking_dir());
        }

        //是否分配终端，并开启交互式启动
        if ("1".equals(containerBean.getTty())) {
            containerCmd.withTty(true);
        }

        try {
            return containerCmd.exec();
        } catch (Exception e) {
            throw new BaseException(e.getMessage());
        }
    }

    /**
     * @Param: [dockerClient, containerCreateBean]
     * @return: TODO
     * @Author: ldl
     * @Create: 2021/01/11 011 09:30
     */
    @Remark("创建容器")
    public static CreateContainerResponse createContainer(SelfDockerClient dockerClient, ContainerBean containerBean) {
        return createContainer(dockerClient.getDockerClient(), containerBean);
    }

    /**
     * @Param: [clientKey, containerCreateBean]
     * @return: TODO
     * @Author: ldl
     * @Create: 2021/01/11 011 09:31
     */
    @Remark("创建容器")
    public static CreateContainerResponse createContainer(String clientKey, ContainerBean containerBean) {
        return createContainer(getDockerClient(clientKey), containerBean);
    }

    /**
     * @Param: [dockerClient, containerId]
     * @return: TODO
     * @Author: ldl
     * @Create: 2021/01/11 011 10:08
     */
    @Remark("删除容器")
    public static boolean removeContainer(DockerClient dockerClient, String containerId) {
        List<Container> containers = containers(dockerClient, containerId, null);
        if (StrKit.notNull(containers) && containers.size() > 0) {
            Container container = containers.get(0);
            if (!"running".equals(container.getState())) {
                dockerClient.removeContainerCmd(containerId).exec();
                return true;
            }
            if (stopContainer(dockerClient, containerId)) {
                dockerClient.removeContainerCmd(containerId).exec();
                return true;
            }
            throw new BaseException("容器删除失败");
        }
        throw new BaseException("容器不存在");
    }

    /**
     * @Param: [clientKey, containerId]
     * @return: TODO
     * @Author: ldl
     * @Create: 2021/01/12 012 11:21
     */
    @Remark("删除容器")
    public static boolean removeContainer(String clientKey, String containerId) {
        return removeContainer(getDockerClient(clientKey), containerId);
    }

    /**
     * @Param: [dockerClient, containerId]
     * @return: TODO
     * @Author: ldl
     * @Create: 2021/01/12 012 11:21
     */
    @Remark("删除容器")
    public static boolean removeContainer(SelfDockerClient dockerClient, String containerId) {
        return removeContainer(dockerClient.getDockerClient(), containerId);
    }

    /**
     * @Param: [clientKey, containerId, pathInContainer, pathOnHost]
     * @return: boolean
     * @Author: ldl
     * @Create: 2021/01/08 008 16:35
     */
    @Remark("从容器中拷贝文件到宿主机")
    public static boolean copyFromContainer(String clientKey, String containerId, String pathInContainer, String pathOnHost) {
        //FIXME 返回执行结果
        return copyFromContainer(getDockerClient(clientKey), containerId, pathInContainer, pathOnHost);
    }

    /**
     * @Param: [selfDockerClient, containerId, pathInContainer, pathOnHost]
     * @return: TODO
     * @Author: ldl
     * @Create: 2021/01/08 008 16:39
     */
    @Remark("从容器中拷贝文件到宿主机")
    public static boolean copyFromContainer(SelfDockerClient selfDockerClient, String containerId, String pathInContainer, String pathOnHost) {
        //FIXME 返回执行结果
        return copyFromContainer(selfDockerClient.getDockerClient(), containerId, pathInContainer, pathOnHost);
    }

    /**
     * @Param: [dockerClient, containerId, pathInContainer, pathOnHost]
     * @return: TODO
     * @Author: ldl
     * @Create: 2021/01/08 008 16:38
     */
    @Remark("从容器中拷贝文件到宿主机")
    public static boolean copyFromContainer(DockerClient dockerClient, String containerId, String pathInContainer, String pathOnHost) {
        CopyArchiveFromContainerCmd copyArchiveFromContainerCmd = dockerClient.copyArchiveFromContainerCmd(containerId, pathInContainer);
        InputStream exec = copyArchiveFromContainerCmd.withHostPath(pathOnHost).exec();

        //FIXME 返回执行结果
        return true;
    }

    /**
     * @Param: [dockerClient, containerId, pathOnHost, pathInContainer]
     * @return: TODO
     * @Author: ldl
     * @Create: 2021/01/08 008 16:49
     */
    @Remark("从宿主机中拷贝文件到容器")
    public static boolean copyToContainer(SelfDockerClient dockerClient, String containerId, String pathOnHost, String pathInContainer) {
        return copyToContainer(dockerClient.getDockerClient(), containerId, pathOnHost, pathInContainer);
    }

    /**
     * @Param: [dockerClient, containerId, pathOnHost, pathInContainer]
     * @return: TODO
     * @Author: ldl
     * @Create: 2021/01/08 008 16:48
     */
    @Remark("从宿主机中拷贝文件到容器")
    public static boolean copyToContainer(String clientKey, String containerId, String pathOnHost, String pathInContainer) {
        return copyToContainer(getDockerClient(clientKey), containerId, pathOnHost, pathInContainer);
    }

    /**
     * @Param: [dockerClient, containerId, pathOnHost, pathInContainer]
     * @return: TODO
     * @Author: ldl
     * @Create: 2021/01/08 008 16:45
     */
    @Remark("从宿主机中拷贝文件到容器")
    public static boolean copyToContainer(DockerClient dockerClient, String containerId, String pathOnHost, String pathInContainer) {
        dockerClient.copyArchiveToContainerCmd(containerId)
                .withDirChildrenOnly(true)
                .withHostResource(pathOnHost)
                .withRemotePath(pathInContainer)
                .exec();
        return true;
    }

    /**
     * @Param: []
     * @return: TODO
     * @Author: ldl
     * @Create: 2020/12/01 001 16:41
     */
    @Remark("获取容器列表")
    public static List<Container> containers(String clientKey, String containerId, String containerName) {
        return containers(getDockerClient(clientKey), containerId, containerName);
    }

    /**
     * @Param: [dockerClient, containerId, containerName]
     * @return: TODO
     * @Author: ldl
     * @Create: 2020/12/31 031 12:06
     */
    @Remark("获取容器列表")
    public static List<Container> containers(SelfDockerClient dockerClient, String containerId, String containerName) {
        return containers(dockerClient.getDockerClient(), containerId, containerName);
    }

    /**
     * @Param: [dockerClient, containerId, containerName]
     * @return: TODO
     * @Author: ldl
     * @Create: 2020/12/31 031 12:05
     */
    @Remark("获取容器列表")
    public static List<Container> containers(DockerClient dockerClient, String containerId, String containerName) {
        ListContainersCmd listContainersCmd = dockerClient.listContainersCmd();
        //是否显示所有的容器,默认为false
        listContainersCmd.withShowAll(true);
        if (StrKit.notBlank(containerId)) {
            //根据容器id进行筛选
            Collection<String> idCollection = new ArrayList<>();
            idCollection.add(containerId);
            listContainersCmd.withIdFilter(idCollection);
        }
        if (StrKit.notBlank(containerName)) {
            //根据名称进行筛选,支持模糊查询
            Collection<String> nameCollection = new ArrayList<>();
            nameCollection.add(containerName);
            listContainersCmd.withNameFilter(nameCollection);
        }
        try {
            return listContainersCmd.exec();
        } catch (Exception e) {
            throw new BaseException(e.getMessage());
        }
    }

    /**
     * @Param: [containerId]
     * @return: TODO
     * @Author: ldl
     * @Create: 2020/12/01 001 16:48
     */
    @Remark("启动容器")
    public static boolean startContainer(String clientKey, String containerId) {
        return startContainer(getDockerClient(clientKey), containerId);
    }

    /**
     * @Param: [clientKey, containerId]
     * @return: TODO
     * @Author: ldl
     * @Create: 2020/12/31 031 12:08
     */
    @Remark("启动容器")
    public static boolean startContainer(SelfDockerClient dockerClient, String containerId) {
        return startContainer(dockerClient.getDockerClient(), containerId);
    }

    /**
     * @Param: [clientKey, containerId]
     * @return: TODO
     * @Author: ldl
     * @Create: 2020/12/31 031 12:08
     */
    @Remark("启动容器")
    public static boolean startContainer(DockerClient dockerClient, String containerId) {
        try {
            dockerClient.startContainerCmd(containerId).exec();
        } catch (Exception e) {
            throw new BaseException(e.getMessage());
        }
        return true;
    }

    /**
     * @Param: [containerId]
     * @return: TODO
     * @Author: ldl
     * @Create: 2020/12/01 001 16:49
     */
    @Remark("重启容器")
    public static boolean restartContainer(String clientKey, String containerId) {
        try {
            getDockerClient(clientKey).restartContainerCmd(containerId).exec();
        } catch (Exception e) {
            throw new BaseException(e.getMessage());
        }
        return true;
    }

    /**
     * @Param: [containerId]
     * @return: TODO
     * @Author: ldl
     * @Create: 2020/12/01 001 16:53
     */
    @Remark("停止容器")
    public static boolean stopContainer(String clientKey, String containerId) {
        try {
            getDockerClient(clientKey).stopContainerCmd(containerId).exec();
        } catch (Exception e) {
            throw new BaseException(e.getMessage());
        }
        return true;
    }

    /**
     * @Param: [dockerClient, containerId]
     * @return: TODO
     * @Author: ldl
     * @Create: 2021/01/11 011 10:24
     */
    @Remark("停止容器")
    public static boolean stopContainer(DockerClient dockerClient, String containerId) {
        try {
            dockerClient.stopContainerCmd(containerId).exec();
        } catch (Exception e) {
            throw new BaseException(e.getMessage());
        }
        return true;
    }

    /**
     * @Param: [containerId]
     * @return: TODO
     * @Author: ldl
     * @Create: 2020/12/01 001 17:09
     */
    @Remark("统计信息")
    public static void stats(String clientKey, String containerId) {
        ResultCallbackTemplate<?, Statistics> start = getDockerClient(clientKey).statsCmd(containerId).start();
        //TODO 待完善
        try {
            start.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * @Param: [dockerClient, containerId, connectKey, data]
     * @return: TODO
     * @Author: ldl
     * @Create: 2021/01/15 015 11:56 更改remark zhl
     */
    @Remark("容器控制台打印")
    public static boolean attachContainer(DockerClient dockerClient, String containerId, String connectKey, String data) {
//        if (StrKit.isBlank(connectKey)) {
//            throw new BaseException("无连接输入");
//        }
        AttachContainerCmd attachContainerCmd = dockerClient.attachContainerCmd(containerId);
        attachContainerCmd.withLogs(true);
        if (StrKit.notBlank(data)) {
            ByteArrayInputStream inputStream = new ByteArrayInputStream(data.getBytes(StandardCharsets.UTF_8));
            attachContainerCmd.withStdIn(inputStream);
        }
        attachContainerCmd.withStdOut(true).exec(new ResultCallback<Frame>() {
            @Override
            public void onStart(Closeable closeable) {
                System.out.println("attach start.");
            }

            @Override
            public void onNext(Frame object) {
                System.out.println("attach next." + "\t"
                                + new String(object.getPayload(), StandardCharsets.UTF_8) + "\t"
//                        + object.getStreamType() + "\t"
//                        + object.toString()
                );
            }

            @Override
            public void onError(Throwable throwable) {
                throwable.printStackTrace();
                System.out.println("attach error." + "\t" + throwable.getMessage());
            }

            @Override
            public void onComplete() {
                System.out.println("attach complete.");
            }

            @Override
            public void close() throws IOException {
                System.out.println("attach close.");
            }
        });
        return true;
    }

    /**
     * @Param: [clientKey, containerId, connectKey, data]
     * @return: TODO
     * @Author: ldl
     * @Create: 2021/01/15 015 12:04
     */
    @Remark("容器控制台操作")
    public static boolean attachContainer(String clientKey, String containerId, String connectKey, String data) {
        return attachContainer(getDockerClient(clientKey), containerId, connectKey, data);
    }

    /**
     * @Param: [dockerClient, containerId, connectKey, data]
     * @return: TODO
     * @Author: ldl
     * @Create: 2021/01/15 015 13:39
     */
    @Remark("容器控制台操作")
    public static boolean attachContainer(SelfDockerClient dockerClient, String containerId, String connectKey, String data) {
        return attachContainer(dockerClient.getDockerClient(), containerId, connectKey, data);
    }

    public static ExecCreateCmdResponse createExecInstance(DockerClient dockerClient, String containerId, String... cmd) {
        ExecCreateCmd execCreateCmd = dockerClient.execCreateCmd(containerId);
        execCreateCmd.withCmd(cmd).withAttachStdout(true).withAttachStderr(true).withTty(true).withAttachStdin(true);
        return execCreateCmd.exec();
    }

    public static void execInstance(String clientKey, String connectKey, String containerId, String... cmd) throws IOException {
        DockerClient dockerClient = DockerKit.getDockerClient(clientKey);
        execInstance(dockerClient, createExecInstance(dockerClient, containerId, cmd).getId(), connectKey);
    }

    public static void execInstance(DockerClient dockerClient, String instanceId, String connectKey) throws IOException {
        ExecStartCmd execStartCmd = dockerClient.execStartCmd(instanceId);
        ShellUtil.DockerConnectInfo dockerConnectInfo = ShellUtil.getDockerConnectInfo(connectKey);
        if (dockerConnectInfo==null){
            throw new BaseException("连接失效或超时");
        }
        try {
            execStartCmd
                    .withTty(true)
                    .withDetach(false)
                    .withStdIn(dockerConnectInfo.getInputStream())
            ;
            execStartCmd.exec(dockerConnectInfo.getResultCallback());
        } catch (Exception e){
            e.printStackTrace();
        }
    }

    private static void resizeExecInstance(DockerClient dockerClient, String instanceId) {
        ResizeExecCmd execStartCmd = dockerClient.resizeExecCmd(instanceId);
        execStartCmd.exec();
    }

    private static void inspectExecInstance(DockerClient dockerClient, String instanceId) {
        InspectExecCmd inspectExecCmd = dockerClient.inspectExecCmd(instanceId);
        InspectExecResponse exec = inspectExecCmd.exec();
        System.out.println("exec.toString() = " + exec.toString());
    }

    /**
     * @Param: [null]
     * @return: TODO
     * @Author: zhl
     * @Create: 2021/1/21 10:14
     **/
    @Remark("获取容器实例信息")
    public static InspectContainerResponse inspectContainer(DockerClient dockerClient, String instanceId) {
        InspectContainerCmd inspectContainerCmd = dockerClient.inspectContainerCmd(instanceId);
        return inspectContainerCmd.exec();
    }

    /**
     * @Param: [null]
     * @return: TODO
     * @Author: zhl
     * @Create: 2021/1/21 10:14
     **/
    @Remark("获取容器名字")
    public static String inspectContainerName(DockerClient dockerClient, String containerId) {
        return inspectContainer(dockerClient, containerId).getName();
    }

}
